﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace NFramework.DataAccess
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
    public class ReaderHelper : DataHelper<ReaderHelper>, IReaderHelper
    {

        #region [ IReaderHelper Members ]

        /// <summary>
        ///     Gets the value of the specified field as a Boolean, or false if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The value of the field, or false if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public bool GetBoolean(string name)
        {
            return GetBoolean(GetOrdinal(name));
        }

        /// <summary>
        ///     Gets the 8-bit unsigned integer value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The 8-bit unsigned integer value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public byte GetByte(string name)
        {
            return GetByte(GetOrdinal(name));
        }

        /// <summary>
        ///     Reads a stream of bytes from the specified field offset into the buffer
        ///     as an array, starting at the given buffer offset.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <param name="fieldoffset">The index within the field from which to start the read operation.</param>
        /// <param name="buffer">The buffer into which to read the stream of bytes.</param>
        /// <param name="bufferoffset">The index for buffer to start the read operation.</param>
        /// <param name="length">The number of bytes to read.</param>
        /// <returns>The actual number of characters read.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public long GetBytes(string name, long fieldOffset, byte[] buffer, int bufferOffset, int length)
        {
            return GetBytes(GetOrdinal(name), fieldOffset, buffer, bufferOffset, length);
        }

        /// <summary>
        ///     Gets the character value of the specified field, or Char.MinValue if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The character value of the specified field, or Char.MinValue if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public char GetChar(string name)
        {
            return GetChar(GetOrdinal(name));
        }

        /// <summary>
        ///     Reads a stream of characters from the specified field offset into the buffer
        ///     as an array, starting at the given buffer offset.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <param name="fieldoffset">The index within the row from which to start the read operation.</param>
        /// <param name="buffer">The buffer into which to read the stream of bytes.</param>
        /// <param name="bufferoffset">The index for buffer to start the read operation.</param>
        /// <param name="length">The number of bytes to read.</param>
        /// <returns>The actual number of characters read.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public long GetChars(string name, long fieldOffset, char[] buffer, int bufferOffset, int length)
        {
            return GetChars(GetOrdinal(name), fieldOffset, buffer, bufferOffset, length);
        }

        /// <summary>
        ///     Returns an System.Data.IDataReader for the specified field ordinal.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>An System.Data.IDataReader.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public System.Data.IDataReader GetData(string name)
        {
            return GetData(GetOrdinal(name));
        }

        /// <summary>
        ///     Gets the data type information for the specified field.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The data type information for the specified field.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public string GetDataTypeName(string name)
        {
            return GetDataTypeName(GetOrdinal(name));
        }

        /// <summary>
        ///     Gets the date and time data value of the specified field, or DateTime.MinValue if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The date and time data value of the specified field, or DateTime.MinValue if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public DateTime GetDateTime(string name)
        {
            return GetDateTime(GetOrdinal(name));
        }

        /// <summary>
        ///     Gets the fixed-position numeric value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The fixed-position numeric value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public decimal GetDecimal(string name)
        {
            return GetDecimal(GetOrdinal(name));
        }

        /// <summary>
        ///     Gets the double-precision floating point number of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The double-precision floating point number of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public double GetDouble(string name)
        {
            return GetDouble(GetOrdinal(name));
        }

        /// <summary>
        ///    Gets the System.Type information corresponding to the type of System.Object
        ///    that would be returned from System.Data.IDataRecord.GetValue(System.Int32).
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>
        ///     The System.Type information corresponding to the type of System.Object that
        ///     would be returned from System.Data.IDataRecord.GetValue(System.Int32).
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public Type GetFieldType(string name)
        {
            return GetFieldType(GetOrdinal(name));
        }

        /// <summary>
        ///     Gets the single-precision floating point number of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The single-precision floating point number of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public float GetFloat(string name)
        {
            return GetFloat(GetOrdinal(name));
        }

        /// <summary>
        ///     Returns the GUID value of the specified field, or Guid.Empty if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The GUID value of the specified field, or Guid.Empty if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public Guid GetGuid(string name)
        {
            return GetGuid(GetOrdinal(name));
        }

        /// <summary>
        ///     Gets the 16-bit signed integer value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The 16-bit signed integer value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public short GetInt16(string name)
        {
            return GetInt16(GetOrdinal(name));
        }

        /// <summary>
        ///     Gets the 32-bit signed integer value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The 32-bit signed integer value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public int GetInt32(string name)
        {
            return GetInt32(GetOrdinal(name));
        }

        /// <summary>
        ///     Gets the 64-bit signed integer value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The 64-bit signed integer value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public long GetInt64(string name)
        {
            return GetInt64(GetOrdinal(name));
        }

        /// <summary>
        ///    Gets the string value of the specified field.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The string value of the specified field.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public string GetString(string name)
        {
            return GetString(GetOrdinal(name));
        }

        /// <summary>
        ///     Return the value of the specified field.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The System.Object which will contain the field value upon return.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public object GetValue(string name)
        {
            return GetValue(GetOrdinal(name));
        }

        /// <summary>
        ///     Return whether the specified field is set to null.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>true if the specified field is set to null; otherwise, false.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public bool IsDBNull(string name)
        {
            return IsDBNull(GetOrdinal(name));
        }

        #endregion

        #region [ IDataReader Members ]

        /// <summary>
        ///     Return the underlying data reader object that contains the data from the data source.
		/// </summary>
        /// <returns>The internal data reader object.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper, and the underlying data reader object is null.
        /// </exception>
        protected IDataReader DataReader
        {
            get 
            {
                if (_dataReader == null)
                {
                    throw new System.InvalidOperationException("There is no data is available: Call Read() to populate the data.");
                }
                return _dataReader; 
            }
        }
        private IDataReader _dataReader;

        protected virtual IDataReader ExecuteReader()
        {
            return ExecuteHelper<IDataReader>(() => Command.ExecuteReader());
        }

        /// <summary>
        ///     Gets a value indicating the depth of nesting for the current row.
        /// </summary>
        /// <returns>The level of nesting.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        public int Depth
        {
            get { return DataReader.Depth; }
        }

        /// <summary>
        ///     Returns a System.Data.DataTable that describes the column metadata of the
        ///     System.Data.IDataReader.
        /// </summary>
        /// <returns>A System.Data.DataTable that describes the column metadata.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exceptions cref="System.InvalidOperationException">
        ///     The System.Data.IDataReader is closed.
        /// </exceptions>
        public System.Data.DataTable GetSchemaTable()
        {
            return DataReader.GetSchemaTable();
        }

        /// <summary>
        ///     Gets a value indicating whether the data reader is closed.
        /// </summary>
        /// <returns>true if uninitialized or if the data reader is closed; otherwise, false.</returns>
        public bool IsClosed
        {
            get { return _dataReader == null || DataReader.IsClosed; }
        }

        /// <summary>
        ///     Initializes the DataReader if uninitialized or closed, and advances it to the next result, 
        ///     when reading the results of batch SQL statements.
        /// </summary>
        /// <returns>true if there are more rows; otherwise, false.</returns>
        public bool NextResult()
        {
            if (IsClosed) { _dataReader = ExecuteReader(); }
            return DataReader.NextResult();
        }

        /// <summary>
        ///     Initializes the DataReader if uninitialized or closed, and advances it to the next record.
        /// </summary>
        /// <returns>true if there are more rows; otherwise, false.</returns>
        public bool Read()
        {
            if (IsClosed) { _dataReader = ExecuteReader(); }
			return DataReader.Read();
        }

        /// <summary>
        ///     Gets the number of rows changed, inserted, or deleted by execution of the
        ///     SQL statement.
        /// </summary>
        /// <returns>
        ///     The number of rows changed, inserted, or deleted; 0 if no rows were affected
        ///     or the statement failed; and -1 for SELECT statements.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        public int RecordsAffected
        {
            get { return DataReader.RecordsAffected; }
        }

        #endregion

        private T GetValueOrDefault<T>(int i, Func<int, T> valueGetter)
        {
            return IsDBNull(i) ? default(T) : valueGetter.Invoke(i);
        }

        #region [ IDataRecord Members ]

        /// <summary>
        ///     Gets the number of fields in the current row.
        /// </summary>
        /// <returns>
        ///     When not positioned in a valid recordset, 0; otherwise, the number of fields
        ///     in the current record. The default is -1.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        public int FieldCount
        {
            get { return DataReader.FieldCount; }
        }

        /// <summary>
        ///     Gets the value of the specified field as a Boolean, or false if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The value of the field, or false if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public bool GetBoolean(int i)
        {
            return GetValueOrDefault<bool>(i, index => DataReader.GetBoolean(index));
        }

        /// <summary>
        ///     Gets the 8-bit unsigned integer value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The 8-bit unsigned integer value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public byte GetByte(int i)
        {
            return GetValueOrDefault<byte>(i, index => DataReader.GetByte(index));
        }

        /// <summary>
        ///     Reads a stream of bytes from the specified field offset into the buffer
        ///     as an array, starting at the given buffer offset.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <param name="fieldoffset">The index within the field from which to start the read operation.</param>
        /// <param name="buffer">The buffer into which to read the stream of bytes.</param>
        /// <param name="bufferoffset">The index for buffer to start the read operation.</param>
        /// <param name="length">The number of bytes to read.</param>
        /// <returns>The actual number of characters read.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
        {
            return DataReader.GetBytes(i, fieldOffset, buffer, bufferoffset, length);
        }

        /// <summary>
        ///     Gets the character value of the specified field, or Char.MinValue if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The character value of the specified field, or Char.MinValue if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public char GetChar(int i)
        {
            return GetValueOrDefault<char>(i, index => DataReader.GetChar(index));
        }

        /// <summary>
        ///     Reads a stream of characters from the specified field offset into the buffer
        ///     as an array, starting at the given buffer offset.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <param name="fieldoffset">The index within the row from which to start the read operation.</param>
        /// <param name="buffer">The buffer into which to read the stream of bytes.</param>
        /// <param name="bufferoffset">The index for buffer to start the read operation.</param>
        /// <param name="length">The number of bytes to read.</param>
        /// <returns>The actual number of characters read.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
        {
            return DataReader.GetChars(i, fieldoffset, buffer, bufferoffset, length);
        }

        /// <summary>
        ///     Returns an System.Data.IDataReader for the specified field ordinal.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>An System.Data.IDataReader.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public System.Data.IDataReader GetData(int i)
        {
            return DataReader.GetData(i);
        }

        /// <summary>
        ///     Gets the data type information for the specified field.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The data type information for the specified field.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public string GetDataTypeName(int i)
        {
            return DataReader.GetDataTypeName(i);
        }

        /// <summary>
        ///     Gets the date and time data value of the specified field, or DateTime.MinValue if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The date and time data value of the specified field, or DateTime.MinValue if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public DateTime GetDateTime(int i)
        {
            return GetValueOrDefault<DateTime>(i, index => DataReader.GetDateTime(index));
        }

        /// <summary>
        ///     Gets the fixed-position numeric value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The fixed-position numeric value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public decimal GetDecimal(int i)
        {
            return GetValueOrDefault<decimal>(i, index => DataReader.GetDecimal(index));
        }

        /// <summary>
        ///     Gets the double-precision floating point number of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The double-precision floating point number of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public double GetDouble(int i)
        {
            return GetValueOrDefault<double>(i, index => DataReader.GetDouble(index));
        }

        /// <summary>
        ///    Gets the System.Type information corresponding to the type of System.Object
        ///    that would be returned from System.Data.IDataRecord.GetValue(System.Int32).
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>
        ///     The System.Type information corresponding to the type of System.Object that
        ///     would be returned from System.Data.IDataRecord.GetValue(System.Int32).
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public Type GetFieldType(int i)
        {
            return DataReader.GetFieldType(i);
        }

        /// <summary>
        ///     Gets the single-precision floating point number of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The single-precision floating point number of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public float GetFloat(int i)
        {
            return GetValueOrDefault<float>(i, index => DataReader.GetFloat(index));
        }

        /// <summary>
        ///     Returns the GUID value of the specified field, or Guid.Empty if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The GUID value of the specified field, or Guid.Empty if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public Guid GetGuid(int i)
        {
            return GetValueOrDefault<Guid>(i, index => DataReader.GetGuid(index));
        }

        /// <summary>
        ///     Gets the 16-bit signed integer value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The 16-bit signed integer value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public short GetInt16(int i)
        {
            return GetValueOrDefault<short>(i, index => DataReader.GetInt16(index));
        }

        /// <summary>
        ///     Gets the 32-bit signed integer value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The 32-bit signed integer value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public int GetInt32(int i)
        {
            return GetValueOrDefault<int>(i, index => DataReader.GetInt32(index));
        }

        /// <summary>
        ///     Gets the 64-bit signed integer value of the specified field, or 0 if the value is DBNull.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The 64-bit signed integer value of the specified field, or 0 if the value is DBNull.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public long GetInt64(int i)
        {
            return GetValueOrDefault<long>(i, index => DataReader.GetInt64(index));
        }

        /// <summary>
        ///     Gets the name for the field to find.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The name of the field or the empty string (""), if there is no value to return.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public string GetName(int i)
        {
            return DataReader.GetName(i);
        }

        /// <summary>
        ///     Return the index of the named field.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The index of the named field.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        public int GetOrdinal(string name)
        {
            return DataReader.GetOrdinal(name);
        }

        /// <summary>
        ///    Gets the string value of the specified field.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The string value of the specified field.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public string GetString(int i)
        {
            return GetValueOrDefault<string>(i, index => DataReader.GetString(index));
        }

        /// <summary>
        ///     Return the value of the specified field.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>The System.Object which will contain the field value upon return.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public object GetValue(int i)
        {
            return DataReader.GetValue(i);
        }

        /// <summary>
        ///     Gets all the attribute fields in the collection for the current record.
        /// </summary>
        /// <param name="values">An array of System.Object to copy the attribute fields into.</param>
        /// <returns>The number of instances of System.Object in the array.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        public int GetValues(object[] values)
        {
            return DataReader.GetValues(values);
        }

        /// <summary>
        ///     Return whether the specified field is set to null.
        /// </summary>
        /// <param name="i">The zero-based field ordinal.</param>
        /// <returns>true if the specified field is set to null; otherwise, false.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public bool IsDBNull(int i)
        {
            return DataReader.IsDBNull(i);
        }

        /// <summary>
        ///     Gets the field with the specified name.
        /// </summary>
        /// <param name="name">The name of the field to find.</param>
        /// <returns>The field with the specified name as an System.Object.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     No field with the specified name was found.
        /// </exception>
        public object this[string name]
        {
            get { return this[GetOrdinal(name)]; }
        }

        /// <summary>
        ///     Gets the field located at the specified index.
        /// </summary>
        /// <param name="i">The zero-based index of the field to get.</param>
        /// <returns>The field located at the specified index as an System.Object.</returns>
        /// <exception cref="System.InvalidOperationException">
        ///     No data has been read into the ReaderHelper.
        /// </exception>
        /// <exception cref="System.IndexOutOfRangeException">
        ///     The index passed was outside the range of 0 through System.Data.IDataRecord.FieldCount.
        /// </exception>
        public object this[int i]
        {
            get
            {
                return GetValueOrDefault<object>(i, index => DataReader[index]);
            }
        }

        #endregion
    }
}
